Razvoj softvera - Primeri, čas 4

Saša Malkov

p00.unikat.cpp

#include <iostream> using namespace std; class PrimerUnikata { public: ... }; // primeri upotrebe void test1() { cout << "test1::pocetak" << endl; ... cout << "test1::kraj" << endl; } void test2() { cout << "test2::pocetak" << endl; ... cout << "test2::kraj" << endl; } int main() { cout << "main::pocetak" << endl; ... test1(); test2(); cout << "main::kraj" << endl; return 0; }

p01.unikat.cpp

#include <iostream> using namespace std; class PrimerUnikata { public: // metod koji vraca primerak unikata static PrimerUnikata& Primerak() { static PrimerUnikata primerak {}; return primerak; // Alternativa 1 // ----------------- // Nije idealno resenje, zato sto se objekat nikada ne unistava. // Ipak, u nekim slucajevima redosled unistavanja medjusobno // referisanih unikata moze da napravi probleme, pa tada // meze biti opravdana odluka da neki unikat ostane neobrisan. /* static PrimerUnikata* p = new PrimerUnikata(); return *p; */ // Alternativa 2 // ----------------- // Iako izgleda da je ovo resenje ekvivalentno prethodnom, // ono nije dobro iz vise razloga. // Najvaznije je da ovaj kod nije bezbedan po niti. // Ako dve niti "istovremeno" zatraze jos uvek neinicijalizovan // primerak unikata, moze da dodje do dvostruke konstrukcije. // Pored toga, kao i u alt.1, postoji curenje memorije. // Dalje, resenje ne moze samo u zaglavlje, jer mora da se // definise podatak "_Primerak". /* // Pretpostavlja se dodavanje privatnog podatka klase: // private: // static T* _Primerak = 0; if( !_Primerak ) _Primerak = new PrimerUnikata(); return *_Primerak; */ } // primer metoda, samo broji upotrebe // kako bi bilo jasno da se sve upotrebe odnose na isti objekat void Metod() { cout << ++Brojac_ << endl; } private: // brojac poziva metoda Metod() int Brojac_; // Konstruktor mora da bude privatan, // da niko ne bi mogao da pravi dodatne objekte ove klase. PrimerUnikata() : Brojac_(0) {} // Naredne deklaracije onemogucavaju upotrebu // konstruktora kopije i operatora dodeljivanja. // (moguce od C++11) PrimerUnikata( const PrimerUnikata& ) = delete; PrimerUnikata& operator=( const PrimerUnikata& ) = delete; // U starijim verzijama je bilo potrebno da se to radi // malo komplikovanije: // 1. deklarisu se privatno, pa niko van klase ne moze da ih koristi // 2. ne implementiraju se, pa ne mogu da se koriste ni u klasi }; // primeri upotrebe void test1() { cout << "test1::pocetak" << endl; PrimerUnikata::Primerak().Metod(); cout << "test1::kraj" << endl; } void test2() { cout << "test2::pocetak" << endl; PrimerUnikata& s = PrimerUnikata::Primerak(); s.Metod(); s.Metod(); test1(); cout << "test2::kraj" << endl; } int main() { cout << "main::pocetak" << endl; PrimerUnikata::Primerak().Metod(); test1(); test2(); PrimerUnikata::Primerak().Metod(); cout << "main::kraj" << endl; return 0; }

p11.composite.cpp

#define _USE_MATH_DEFINES #include <cmath> #include <iostream> #include <vector> using namespace std; // kompozitna klasa (nekompletna) namespace Geometrija { //-------------------------------------------------- class Tacka { public: Tacka( double x, double y ) : X_(x), Y_(y) {} ~Tacka() { cout << "~Tacka " << *this << endl; } private: double X_; double Y_; friend ostream& operator<<( ostream&, const Tacka& ); friend istream& operator>>( istream&, Tacka& ); }; //-------------------------------------------------- ostream& operator<<( ostream& ostr, const Tacka& t ) { ostr << "(" << t.X_ << "," << t.Y_ << ")"; return ostr; } istream& operator>>( istream& istr, Tacka& a ) { char c1,c2,c3; istr >> c1 >> a.X_ >> c2 >> a.Y_ >> c3; if( c1!='(' || c2!=',' || c3!=')' ) istr.setstate( ios::failbit ); return istr; } //-------------------------------------------------- class Lik { public: Lik( double x, double y ) : Polozaj_(x,y) { BrojLikova++; } Lik( const Lik& lik ) : Polozaj_( lik.Polozaj_ ) { BrojLikova++; } virtual ~Lik() { cout << "~Lik" << endl; BrojLikova--; } const Tacka& Polozaj() const { return Polozaj_; } virtual double Povrsina() const = 0; virtual const char* NazivKlase() const = 0; virtual void Ispisi( ostream& ostr ) const { ostr << NazivKlase() << Polozaj() << " : P=" << Povrsina(); } static unsigned BrojLikova; private: Tacka Polozaj_; }; unsigned Lik::BrojLikova = 0; ostream& operator<<( ostream& ostr, const Lik& lik ) { lik.Ispisi(ostr); return ostr; } //-------------------------------------------------- class Pravougaonik : public Lik { public: Pravougaonik( double x, double y, double s, double v ) : Lik(x,y), Sirina_(s), Visina_(v) {} ~Pravougaonik() { cout << "~Pravougaonik" << endl; } double Sirina() const { return Sirina_; } double Visina() const { return Visina_; } const char* NazivKlase() const { return "Pravougaonik"; } double Povrsina() const { return Sirina() * Visina(); } void Ispisi( ostream& ostr ) const { Lik::Ispisi(ostr); ostr << " : a,b=" << Sirina() << "," << Visina(); } private: double Sirina_; double Visina_; }; //-------------------------------------------------- class Kvadrat : public Pravougaonik { public: Kvadrat( double x, double y, double a ) : Pravougaonik( x, y, a, a ) {} ~Kvadrat() { cout << "~Kvadrat" << endl; } const char* NazivKlase() const { return "Kvadrat"; } }; //-------------------------------------------------- class Krug : public Lik { public: Krug( double x, double y, double r ) : Lik(x,y), R_(r) {} ~Krug() { cout << "~Krug" << endl; } double R() const { return R_; } const char* NazivKlase() const { return "Krug"; } double Povrsina() const { return R() * R() * M_PI; } void Ispisi( ostream& ostr ) const { Lik::Ispisi(ostr); ostr << " : r=" << R(); } private: double R_; }; //-------------------------------------------------- class SlozenLik : public Lik { public: SlozenLik( double x, double y ) : Lik(x,y) {} ~SlozenLik() { cout << "~SlozenLik" << endl; for( auto lik: Likovi_ ) delete lik; } void Dodaj( Lik* l ) { Likovi_.push_back(l); } double Povrsina() const { double p = 0; for( auto lik: Likovi_ ) p += lik->Povrsina(); return p; } const char* NazivKlase() const { return "SlozenLik"; } private: vector<Lik*> Likovi_; }; } // namespace Geometrija //-------------------------------------------------- using namespace Geometrija; int main() { { SlozenLik sl(0,0); sl.Dodaj( new Pravougaonik(1,2,3,4) ); sl.Dodaj( new Kvadrat(5,6,7) ); sl.Dodaj( new Krug(8,9,10) ); SlozenLik* sl2 = new SlozenLik(1,1); sl2->Dodaj( new Krug(2,3,4)); sl2->Dodaj( new Kvadrat(2,4,5)); sl.Dodaj(sl2); cout << sl << endl; cout << Lik::BrojLikova << endl; } //svi likovi su obrisani cout << Lik::BrojLikova << endl; return 0; }

p12.composite.cpp

#define _USE_MATH_DEFINES #include <cmath> #include <vector> #include <iostream> using namespace std; // kompozitna klasa (kompletna, sa virtualnim kopiranjem) namespace Geometrija { //-------------------------------------------------- class Tacka { public: Tacka( double x, double y ) : X_(x), Y_(y) {} ~Tacka() { cout << "~Tacka " << *this << endl; } private: double X_; double Y_; friend ostream& operator<<( ostream&, const Tacka& ); friend istream& operator>>( istream&, Tacka& ); }; //-------------------------------------------------- ostream& operator<<( ostream& ostr, const Tacka& t ) { ostr << "(" << t.X_ << "," << t.Y_ << ")"; return ostr; } istream& operator>>( istream& istr, Tacka& a ) { char c1,c2,c3; istr >> c1 >> a.X_ >> c2 >> a.Y_ >> c3; if( c1!='(' || c2!=',' || c3!=')' ) istr.setstate( ios::failbit ); return istr; } //-------------------------------------------------- class Lik { public: Lik( double x, double y ) : Polozaj_(x,y) { BrojLikova++; } Lik( const Lik& l ) : Polozaj_( l.Polozaj() ) { BrojLikova++; } virtual ~Lik() { cout << "~Lik" << endl; BrojLikova--; } virtual Lik* Kopija() const = 0; Tacka& Polozaj() { return Polozaj_; } const Tacka& Polozaj() const { return Polozaj_; } virtual double Povrsina() const = 0; virtual const char* NazivKlase() const = 0; virtual void Ispisi( ostream& ostr ) const { ostr << NazivKlase() << Polozaj() << " : P=" << Povrsina(); } static unsigned BrojLikova; private: Tacka Polozaj_; }; unsigned Lik::BrojLikova = 0; ostream& operator<<( ostream& ostr, const Lik& lik ) { lik.Ispisi(ostr); return ostr; } //-------------------------------------------------- class Pravougaonik : public Lik { public: Pravougaonik( double x, double y, double s, double v ) : Lik(x,y), Sirina_(s), Visina_(v) {} ~Pravougaonik() { cout << "~Pravougaonik" << endl; } Lik* Kopija() const { return new Pravougaonik(*this); } double Sirina() const { return Sirina_; } double Visina() const { return Visina_; } const char* NazivKlase() const { return "Pravougaonik"; } double Povrsina() const { return Sirina() * Visina(); } void Ispisi( ostream& ostr ) const { Lik::Ispisi(ostr); ostr << " : a,b=" << Sirina() << "," << Visina(); } private: double Sirina_; double Visina_; }; //-------------------------------------------------- class Kvadrat : public Pravougaonik { public: Kvadrat( double x, double y, double a ) : Pravougaonik( x, y, a, a ) {} ~Kvadrat() { cout << "~Kvadrat" << endl; } Lik* Kopija() const { return new Kvadrat(*this); } const char* NazivKlase() const { return "Kvadrat"; } }; //-------------------------------------------------- class Krug : public Lik { public: Krug( double x, double y, double r ) : Lik(x,y), R_(r) {} ~Krug() { cout << "~Krug" << endl; } Lik* Kopija() const { return new Krug(*this); } double R() const { return R_; } const char* NazivKlase() const { return "Krug"; } double Povrsina() const { return R() * R() * M_PI; } void Ispisi( ostream& ostr ) const { Lik::Ispisi(ostr); ostr << " : r=" << R(); } private: double R_; }; //-------------------------------------------------- class SlozenLik : public Lik { public: SlozenLik( double x, double y ) : Lik(x,y) {} SlozenLik( const SlozenLik& sl ) : Lik(sl) { init( sl ); } ~SlozenLik() { cout << "~SlozenLik" << endl; deinit(); } SlozenLik& operator=( const SlozenLik& sl ) { if( &sl != this ){ deinit(); Polozaj() = sl.Polozaj(); init(sl); } return *this; } Lik* Kopija() const { return new SlozenLik(*this); } void Dodaj( Lik* l ) { Likovi_.push_back(l); } double Povrsina() const { double p = 0; for( auto lik: Likovi_ ) p += lik->Povrsina(); return p; } const char* NazivKlase() const { return "SlozenLik"; } private: void deinit() { for( auto lik: Likovi_ ) delete lik; Likovi_.clear(); } void init( const SlozenLik& sl ) { for( auto lik: sl.Likovi_ ) Dodaj( lik->Kopija() ); } vector<Lik*> Likovi_; }; } // namespace Geometrija using namespace Geometrija; //-------------------------------------------------- int main() { cout << "Broj likova = " << Lik::BrojLikova << endl; { SlozenLik sl(0,0); sl.Dodaj( new Pravougaonik(1,2,3,4) ); sl.Dodaj( new Kvadrat(5,6,7) ); sl.Dodaj( new Krug(8,9,10) ); SlozenLik* sl2 = new SlozenLik(1,1); sl2->Dodaj( new Krug(2,3,4)); sl2->Dodaj( new Kvadrat(2,4,5)); sl.Dodaj(sl2); cout << sl << endl; cout << "Broj likova = " << Lik::BrojLikova << endl; SlozenLik sl3 = sl; cout << sl3 << endl; cout << sl << endl; cout << "Broj likova = " << Lik::BrojLikova << endl; SlozenLik sl4 = sl; cout << sl4 << endl; sl4 = sl3; cout << sl4 << endl; cout << "Broj likova = " << Lik::BrojLikova << endl; } cout << "Broj likova = " << Lik::BrojLikova << endl; return 0; }

p21.posetilac.cpp

#define _USE_MATH_DEFINES #include <cmath> #include <iostream> #include <vector> using namespace std; // Pocinjemo od jednog od ranijih primera. // Fokus je na nacinu izracunavanja povrsine. //---------------------------------------------------------------- class Tacka { public: Tacka( double x, double y ) : X_(x), Y_(y) {} private: double X_; double Y_; friend ostream& operator<<( ostream&, const Tacka& ); friend istream& operator>>( istream&, Tacka& ); }; ostream& operator<<( ostream& ostr, const Tacka& t ) { ostr << "(" << t.X_ << "," << t.Y_ << ")"; return ostr; } istream& operator>>( istream& istr, Tacka& a ) { char c1,c2,c3; istr >> c1 >> a.X_ >> c2 >> a.Y_ >> c3; if( c1!='(' || c2!=',' || c3!=')' ) istr.setstate( ios::failbit ); return istr; } //---------------------------------------------------------------- class Lik { public: Lik( double x, double y ) : Polozaj_(x,y) {} virtual ~Lik() {} virtual Lik* Kopija() const = 0; const Tacka& Polozaj() const { return Polozaj_; } Tacka& Polozaj() { return Polozaj_; } // Klasican pristup problemu racunanja povrsine. virtual double Povrsina() const = 0; private: Tacka Polozaj_; }; ostream& operator<<( ostream& ostr, const Lik& l ) { ostr << l.Polozaj() << " P=" << l.Povrsina(); return ostr; } //---------------------------------------------------------------- class Pravougaonik : public Lik { public: Pravougaonik( double x, double y, double s, double v ) : Lik(x,y), Sirina_(s), Visina_(v) {} Lik* Kopija() const { return new Pravougaonik(*this); } double Sirina() const { return Sirina_; } double Visina() const { return Visina_; } double Povrsina() const { return Sirina() * Visina(); } private: double Sirina_; double Visina_; }; //---------------------------------------------------------------- class Kvadrat : public Pravougaonik { public: Kvadrat( double x, double y, double a ) : Pravougaonik( x, y, a, a ) {} Lik* Kopija() const { return new Kvadrat(*this); } }; //---------------------------------------------------------------- class Krug : public Lik { public: Krug( double x, double y, double r ) : Lik(x,y), R_(r) {} Lik* Kopija() const { return new Krug(*this); } double R() const { return R_; } double Povrsina() const { return R() * R() * M_PI; } private: double R_; }; //---------------------------------------------------------------- class SlozenLik : public Lik { public: SlozenLik( double x, double y ) : Lik(x,y) {} SlozenLik( const SlozenLik& sl ) : Lik(sl) { init( sl ); } ~SlozenLik() { deinit(); } SlozenLik& operator=( const SlozenLik& sl ) { if( &sl != this ){ deinit(); Polozaj() = sl.Polozaj(); init(sl); } return *this; } Lik* Kopija() const { return new SlozenLik(*this); } void Dodaj( Lik* l ) { Likovi_.push_back(l); } double Povrsina() const { double p = 0; for( auto lik: Likovi_ ) p += lik->Povrsina(); return p; } private: vector<Lik*> Likovi_; void deinit() { for( auto lik: Likovi_ ) delete lik; Likovi_.clear(); } void init( const SlozenLik& sl ) { for( auto lik: sl.Likovi_ ) Dodaj( lik->Kopija() ); } }; //---------------------------------------------------------------- int main() { SlozenLik sl(0,0); sl.Dodaj( new Pravougaonik(1,2,3,4) ); sl.Dodaj( new Kvadrat(5,6,7) ); sl.Dodaj( new Krug(8,9,10) ); SlozenLik* sl2 = new SlozenLik(1,1); sl2->Dodaj( new Krug(2,3,4)); sl2->Dodaj( new Kvadrat(2,4,5)); sl.Dodaj(sl2); cout << sl << endl; return 0; }

p22.posetilac.cpp

#define _USE_MATH_DEFINES #include <cmath> #include <iostream> #include <vector> using namespace std; // Zbog deklarisanja klase PosetilacLikova i njenih metoda 'unapred' // moramo da unapred deklariseno i klase hijerarhije. class Pravougaonik; class Kvadrat; class Krug; class SlozenLik; class PosetilacLikova { public: virtual void PosetiPravougaonik( Pravougaonik& ) = 0; virtual void PosetiKvadrat( Kvadrat& ) = 0; virtual void PosetiKrug( Krug& ) = 0; virtual void PosetiSlozenLik( SlozenLik& ) = 0; }; //---------------------------------------------------------------- class Tacka { public: Tacka( double x, double y ) : X_(x), Y_(y) {} private: double X_; double Y_; friend ostream& operator<<( ostream&, const Tacka& ); friend istream& operator>>( istream&, Tacka& ); }; ostream& operator<<( ostream& ostr, const Tacka& t ) { ostr << "(" << t.X_ << "," << t.Y_ << ")"; return ostr; } istream& operator>>( istream& istr, Tacka& a ) { char c1,c2,c3; istr >> c1 >> a.X_ >> c2 >> a.Y_ >> c3; if( c1!='(' || c2!=',' || c3!=')' ) istr.setstate( ios::failbit ); return istr; } //---------------------------------------------------------------- class Lik { public: Lik( double x, double y ) : Polozaj_(x,y) {} virtual ~Lik() {} virtual Lik* Kopija() const = 0; const Tacka& Polozaj() const { return Polozaj_; } Tacka& Polozaj() { return Polozaj_; } // Klasican pristup problemu racunanja povrsine. virtual double Povrsina() const = 0; // Opsti metod za prihvatanje posete. virtual void PrihvatiPosetu( PosetilacLikova& p ) = 0; private: Tacka Polozaj_; }; ostream& operator<<( ostream& ostr, const Lik& l ) { ostr << l.Polozaj() << " P=" << l.Povrsina(); return ostr; } //---------------------------------------------------------------- class Pravougaonik : public Lik { public: Pravougaonik( double x, double y, double s, double v ) : Lik(x,y), Sirina_(s), Visina_(v) {} Lik* Kopija() const { return new Pravougaonik(*this); } double Sirina() const { return Sirina_; } double Visina() const { return Visina_; } double Povrsina() const { return Sirina() * Visina(); } // Pravougaonik prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas pravougaonik. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiPravougaonik( *this ); } private: double Sirina_; double Visina_; }; //---------------------------------------------------------------- class Kvadrat : public Pravougaonik { public: Kvadrat( double x, double y, double a ) : Pravougaonik( x, y, a, a ) {} // Kvadrat prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas kvadrat. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiKvadrat( *this ); } Lik* Kopija() const { return new Kvadrat(*this); } }; //---------------------------------------------------------------- class Krug : public Lik { public: Krug( double x, double y, double r ) : Lik(x,y), R_(r) {} // Krug prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas krug. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiKrug( *this ); } Lik* Kopija() const { return new Krug(*this); } double R() const { return R_; } double Povrsina() const { return R() * R() * M_PI; } private: double R_; }; //---------------------------------------------------------------- class SlozenLik : public Lik { public: SlozenLik( double x, double y ) : Lik(x,y) {} SlozenLik( const SlozenLik& sl ) : Lik(sl) { init( sl ); } ~SlozenLik() { deinit(); } SlozenLik& operator=( const SlozenLik& sl ) { if( &sl != this ){ deinit(); Polozaj() = sl.Polozaj(); init(sl); } return *this; } // Slozen lik prihvata 'opstu' posetu tako sto usmerava posetioca da poseti slozen lik, // ali i svaki pojedinacan sadrzani lik. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiSlozenLik( *this ); for( auto lik: Likovi_) lik->PrihvatiPosetu(p); } Lik* Kopija() const { return new SlozenLik(*this); } void Dodaj( Lik* l ) { Likovi_.push_back(l); } double Povrsina() const { double p = 0; for( auto lik: Likovi_ ) p += lik->Povrsina(); return p; } private: vector<Lik*> Likovi_; void deinit() { for( auto lik: Likovi_ ) delete lik; Likovi_.clear(); } void init( const SlozenLik& sl ) { for( auto lik: sl.Likovi_ ) Dodaj( lik->Kopija() ); } }; //---------------------------------------------------------------- class RacunanjePovrsine : public PosetilacLikova { public: RacunanjePovrsine() : Povrsina_(0) {} double Povrsina() const { return Povrsina_; } void PosetiPravougaonik( Pravougaonik& p ){ Povrsina_ += p.Sirina() * p.Visina(); } void PosetiKvadrat( Kvadrat& k ){ Povrsina_ += k.Sirina() * k.Visina(); } void PosetiKrug( Krug& k ){ Povrsina_ += k.R() * k.R() * M_PI; } void PosetiSlozenLik( SlozenLik& ){ } private: double Povrsina_; }; int main() { SlozenLik sl(0,0); sl.Dodaj( new Pravougaonik(1,2,3,4) ); sl.Dodaj( new Kvadrat(5,6,7) ); sl.Dodaj( new Krug(8,9,10) ); SlozenLik* sl2 = new SlozenLik(1,1); sl2->Dodaj( new Krug(2,3,4)); sl2->Dodaj( new Kvadrat(2,4,5)); sl.Dodaj(sl2); cout << sl << endl; RacunanjePovrsine rp; sl.PrihvatiPosetu( rp ); cout << rp.Povrsina() << endl; return 0; }

p23.posetilac.cpp

#define _USE_MATH_DEFINES #include <cmath> #include <iostream> #include <vector> using namespace std; // Dopunjavamo posetioca tako da moze da se koristi // poput funkcije. class Pravougaonik; class Kvadrat; class Krug; class SlozenLik; class PosetilacLikova { public: virtual void PosetiPravougaonik( Pravougaonik& ) = 0; virtual void PosetiKvadrat( Kvadrat& ) = 0; virtual void PosetiKrug( Krug& ) = 0; virtual void PosetiSlozenLik( SlozenLik& ) = 0; }; //---------------------------------------------------------------- class Tacka { public: Tacka( double x, double y ) : X_(x), Y_(y) {} private: double X_; double Y_; friend ostream& operator<<( ostream&, const Tacka& ); friend istream& operator>>( istream&, Tacka& ); }; ostream& operator<<( ostream& ostr, const Tacka& t ) { ostr << "(" << t.X_ << "," << t.Y_ << ")"; return ostr; } istream& operator>>( istream& istr, Tacka& a ) { char c1,c2,c3; istr >> c1 >> a.X_ >> c2 >> a.Y_ >> c3; if( c1!='(' || c2!=',' || c3!=')' ) istr.setstate( ios::failbit ); return istr; } //---------------------------------------------------------------- class Lik { public: Lik( double x, double y ) : Polozaj_(x,y) {} virtual ~Lik() {} virtual Lik* Kopija() const = 0; const Tacka& Polozaj() const { return Polozaj_; } Tacka& Polozaj() { return Polozaj_; } // Klasican pristup problemu racunanja povrsine. virtual double Povrsina() const = 0; // Opsti metod za prihvatanje posete. virtual void PrihvatiPosetu( PosetilacLikova& p ) = 0; private: Tacka Polozaj_; }; ostream& operator<<( ostream& ostr, const Lik& l ) { ostr << l.Polozaj() << " P=" << l.Povrsina(); return ostr; } //---------------------------------------------------------------- class Pravougaonik : public Lik { public: Pravougaonik( double x, double y, double s, double v ) : Lik(x,y), Sirina_(s), Visina_(v) {} Lik* Kopija() const { return new Pravougaonik(*this); } double Sirina() const { return Sirina_; } double Visina() const { return Visina_; } double Povrsina() const { return Sirina() * Visina(); } // Pravougaonik prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas pravougaonik. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiPravougaonik( *this ); } private: double Sirina_; double Visina_; }; //---------------------------------------------------------------- class Kvadrat : public Pravougaonik { public: Kvadrat( double x, double y, double a ) : Pravougaonik( x, y, a, a ) {} // Kvadrat prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas kvadrat. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiKvadrat( *this ); } Lik* Kopija() const { return new Kvadrat(*this); } }; //---------------------------------------------------------------- class Krug : public Lik { public: Krug( double x, double y, double r ) : Lik(x,y), R_(r) {} // Krug prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas krug. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiKrug( *this ); } Lik* Kopija() const { return new Krug(*this); } double R() const { return R_; } double Povrsina() const { return R() * R() * M_PI; } private: double R_; }; //---------------------------------------------------------------- class SlozenLik : public Lik { public: SlozenLik( double x, double y ) : Lik(x,y) {} SlozenLik( const SlozenLik& sl ) : Lik(sl) { init( sl ); } ~SlozenLik() { deinit(); } SlozenLik& operator=( const SlozenLik& sl ) { if( &sl != this ){ deinit(); Polozaj() = sl.Polozaj(); init(sl); } return *this; } // Slozen lik prihvata 'opstu' posetu tako sto usmerava posetioca da poseti slozen lik, // ali i svaki pojedinacan sadrzani lik. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiSlozenLik( *this ); for( auto lik: Likovi_) lik->PrihvatiPosetu(p); } Lik* Kopija() const { return new SlozenLik(*this); } void Dodaj( Lik* l ) { Likovi_.push_back(l); } double Povrsina() const { double p = 0; for( auto lik: Likovi_ ) p += lik->Povrsina(); return p; } private: vector<Lik*> Likovi_; void deinit() { for( auto lik: Likovi_ ) delete lik; Likovi_.clear(); } void init( const SlozenLik& sl ) { for( auto lik: sl.Likovi_ ) Dodaj( lik->Kopija() ); } }; //---------------------------------------------------------------- class RacunanjePovrsine : public PosetilacLikova { public: RacunanjePovrsine() : Povrsina_(0) {} RacunanjePovrsine( Lik& lik ) : Povrsina_(0) { lik.PrihvatiPosetu(*this); } double Povrsina() const { return Povrsina_; } operator double() { return Povrsina(); } void PosetiPravougaonik( Pravougaonik& p ){ Povrsina_ += p.Sirina() * p.Visina(); } void PosetiKvadrat( Kvadrat& k ){ Povrsina_ += k.Sirina() * k.Visina(); } void PosetiKrug( Krug& k ){ Povrsina_ += k.R() * k.R() * M_PI; } void PosetiSlozenLik( SlozenLik& ){ } private: double Povrsina_; }; int main() { SlozenLik sl(0,0); sl.Dodaj( new Pravougaonik(1,2,3,4) ); sl.Dodaj( new Kvadrat(5,6,7) ); sl.Dodaj( new Krug(8,9,10) ); SlozenLik* sl2 = new SlozenLik(1,1); sl2->Dodaj( new Krug(2,3,4)); sl2->Dodaj( new Kvadrat(2,4,5)); sl.Dodaj(sl2); cout << sl << endl; cout << RacunanjePovrsine(sl) << endl; return 0; }

p24.posetilac.cpp

#define _USE_MATH_DEFINES #include <cmath> #include <iostream> #include <vector> using namespace std; // Na slican nacin dodajemo posetioca koji racuna obim. //---------------------------------------------------------------- class Tacka { public: Tacka( double x, double y ) : X_(x), Y_(y) {} private: double X_; double Y_; friend ostream& operator<<( ostream&, const Tacka& ); friend istream& operator>>( istream&, Tacka& ); }; ostream& operator<<( ostream& ostr, const Tacka& t ) { ostr << "(" << t.X_ << "," << t.Y_ << ")"; return ostr; } istream& operator>>( istream& istr, Tacka& a ) { char c1,c2,c3; istr >> c1 >> a.X_ >> c2 >> a.Y_ >> c3; if( c1!='(' || c2!=',' || c3!=')' ) istr.setstate( ios::failbit ); return istr; } //---------------------------------------------------------------- // Zbog deklarisanja klase PosetilacLikova i njenih metoda 'unapred' // moramo da unapred deklariseno i klase hijerarhije. class Pravougaonik; class Kvadrat; class Krug; class SlozenLik; class PosetilacLikova { public: virtual void PosetiPravougaonik( Pravougaonik& ) = 0; virtual void PosetiKvadrat( Kvadrat& ) = 0; virtual void PosetiKrug( Krug& ) = 0; virtual void PosetiSlozenLik( SlozenLik& ) = 0; }; //---------------------------------------------------------------- class Lik { public: Lik( double x, double y ) : Polozaj_(x,y) {} virtual ~Lik() {} virtual Lik* Kopija() const = 0; const Tacka& Polozaj() const { return Polozaj_; } Tacka& Polozaj() { return Polozaj_; } // Klasican pristup problemu racunanja povrsine. virtual double Povrsina() const = 0; // Opsti metod za prihvatanje posete. virtual void PrihvatiPosetu( PosetilacLikova& p ) = 0; private: Tacka Polozaj_; }; ostream& operator<<( ostream& ostr, const Lik& l ) { ostr << l.Polozaj() << " P=" << l.Povrsina(); return ostr; } //---------------------------------------------------------------- class Pravougaonik : public Lik { public: Pravougaonik( double x, double y, double s, double v ) : Lik(x,y), Sirina_(s), Visina_(v) {} Lik* Kopija() const { return new Pravougaonik(*this); } double Sirina() const { return Sirina_; } double Visina() const { return Visina_; } double Povrsina() const { return Sirina() * Visina(); } // Pravougaonik prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas pravougaonik. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiPravougaonik( *this ); } private: double Sirina_; double Visina_; }; //---------------------------------------------------------------- class Kvadrat : public Pravougaonik { public: Kvadrat( double x, double y, double a ) : Pravougaonik( x, y, a, a ) {} // Kvadrat prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas kvadrat. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiKvadrat( *this ); } Lik* Kopija() const { return new Kvadrat(*this); } }; //---------------------------------------------------------------- class Krug : public Lik { public: Krug( double x, double y, double r ) : Lik(x,y), R_(r) {} // Krug prihvata 'opstu' posetu tako sto usmerava posetioca // da poseti bas krug. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiKrug( *this ); } Lik* Kopija() const { return new Krug(*this); } double R() const { return R_; } double Povrsina() const { return R() * R() * M_PI; } private: double R_; }; //---------------------------------------------------------------- class SlozenLik : public Lik { public: SlozenLik( double x, double y ) : Lik(x,y) {} SlozenLik( const SlozenLik& sl ) : Lik(sl) { init( sl ); } ~SlozenLik() { deinit(); } SlozenLik& operator=( const SlozenLik& sl ) { if( &sl != this ){ deinit(); Polozaj() = sl.Polozaj(); init(sl); } return *this; } // Slozen lik prihvata 'opstu' posetu tako sto usmerava posetioca da poseti slozen lik, // ali i svaki pojedinacan sadrzani lik. void PrihvatiPosetu( PosetilacLikova& p ) { p.PosetiSlozenLik( *this ); for( auto lik: Likovi_) lik->PrihvatiPosetu(p); } Lik* Kopija() const { return new SlozenLik(*this); } void Dodaj( Lik* l ) { Likovi_.push_back(l); } double Povrsina() const { double p = 0; for( auto lik: Likovi_ ) p += lik->Povrsina(); return p; } private: vector<Lik*> Likovi_; void deinit() { for( auto lik: Likovi_ ) delete lik; Likovi_.clear(); } void init( const SlozenLik& sl ) { for( auto lik: sl.Likovi_ ) Dodaj( lik->Kopija() ); } }; //---------------------------------------------------------------- class RacunanjePovrsine : public PosetilacLikova { public: RacunanjePovrsine() : Povrsina_(0) {} RacunanjePovrsine( Lik& lik ) : Povrsina_(0) { lik.PrihvatiPosetu(*this); } double Povrsina() const { return Povrsina_; } operator double() { return Povrsina(); } void PosetiPravougaonik( Pravougaonik& p ) { Povrsina_ += p.Sirina() * p.Visina(); } void PosetiKvadrat( Kvadrat& k ) { Povrsina_ += k.Sirina() * k.Visina(); } void PosetiKrug( Krug& k ) { Povrsina_ += k.R() * k.R() * M_PI; } void PosetiSlozenLik( SlozenLik& ) {} private: double Povrsina_; }; class RacunanjeObima : public PosetilacLikova { public: RacunanjeObima() : Obim_(0) {} RacunanjeObima( Lik& lik ) : Obim_(0) { lik.PrihvatiPosetu(*this); } double Obim() const { return Obim_; } operator double() { return Obim(); } void PosetiPravougaonik( Pravougaonik& p ) { Obim_ += 2 * ( p.Sirina() + p.Visina()); } void PosetiKvadrat( Kvadrat& k ) { Obim_ += 4 * k.Sirina(); } void PosetiKrug( Krug& k ) { Obim_ += 2* k.R() * M_PI; } void PosetiSlozenLik( SlozenLik& ) { } private: double Obim_; }; int main() { SlozenLik sl(0,0); sl.Dodaj( new Pravougaonik(1,2,3,4) ); sl.Dodaj( new Kvadrat(5,6,7) ); sl.Dodaj( new Krug(8,9,10) ); SlozenLik* sl2 = new SlozenLik(1,1); sl2->Dodaj( new Krug(2,3,4)); sl2->Dodaj( new Kvadrat(2,4,5)); sl.Dodaj(sl2); cout << sl << endl; cout << RacunanjePovrsine(sl) << endl; cout << RacunanjeObima(sl) << endl; return 0; }

p31.posmatrac.cpp

#define _USE_MATH_DEFINES #include <cmath> #include <iostream> #include <vector> using namespace std; //---------------------------------------------------------------- class Tacka { public: Tacka( double x, double y ) : X_(x), Y_(y) {} private: double X_; double Y_; friend ostream& operator<<( ostream&, const Tacka& ); friend istream& operator>>( istream&, Tacka& ); }; ostream& operator<<( ostream& ostr, const Tacka& t ) { ostr << "(" << t.X_ << "," << t.Y_ << ")"; return ostr; } istream& operator>>( istream& istr, Tacka& a ) { char c1,c2,c3; istr >> c1 >> a.X_ >> c2 >> a.Y_ >> c3; if( c1!='(' || c2!=',' || c3!=')' ) istr.setstate( ios::failbit ); return istr; } //---------------------------------------------------------------- class Lik { public: Lik( double x, double y ) : Polozaj_(x,y) {} virtual ~Lik() {} virtual Lik* Kopija() const = 0; const Tacka& Polozaj() const { return Polozaj_; } Tacka& Polozaj() { return Polozaj_; } virtual double Povrsina() const = 0; // primer promene koja obavestava posmatrace void Pomeri( double nx, double ny ) { Polozaj_ = Tacka( nx, ny ); } private: Tacka Polozaj_; }; ostream& operator<<( ostream& ostr, const Lik& l ) { ostr << l.Polozaj() << " P=" << l.Povrsina(); return ostr; } //---------------------------------------------------------------- class Pravougaonik : public Lik { public: Pravougaonik( double x, double y, double s, double v ) : Lik(x,y), Sirina_(s), Visina_(v) {} Lik* Kopija() const { return new Pravougaonik(*this); } double Sirina() const { return Sirina_; } double Visina() const { return Visina_; } double Povrsina() const { return Sirina() * Visina(); } private: double Sirina_; double Visina_; }; //---------------------------------------------------------------- class Kvadrat : public Pravougaonik { public: Kvadrat( double x, double y, double a ) : Pravougaonik( x, y, a, a ) {} Lik* Kopija() const { return new Kvadrat(*this); } }; //---------------------------------------------------------------- class Krug : public Lik { public: Krug( double x, double y, double r ) : Lik(x,y), R_(r) {} Lik* Kopija() const { return new Krug(*this); } double R() const { return R_; } double Povrsina() const { return R() * R() * M_PI; } private: double R_; }; //---------------------------------------------------------------- class SlozenLik : public Lik { public: SlozenLik( double x, double y ) : Lik(x,y) {} SlozenLik( const SlozenLik& sl ) : Lik(sl) { init( sl ); } ~SlozenLik() { deinit(); } SlozenLik& operator=( const SlozenLik& sl ) { if( &sl != this ){ deinit(); Polozaj() = sl.Polozaj(); init(sl); } return *this; } Lik* Kopija() const { return new SlozenLik(*this); } void Dodaj( Lik* l ) { Likovi_.push_back(l); } double Povrsina() const { double p = 0; for( auto lik: Likovi_ ) p += lik->Povrsina(); return p; } private: vector<Lik*> Likovi_; void deinit() { for( auto lik: Likovi_ ) delete lik; Likovi_.clear(); } void init( const SlozenLik& sl ) { for( auto lik: sl.Likovi_ ) Dodaj( lik->Kopija() ); } }; //---------------------------------------------------------------- int main() { SlozenLik sl(0,0); sl.Dodaj( new Pravougaonik(1,2,3,4) ); sl.Dodaj( new Kvadrat(5,6,7) ); sl.Dodaj( new Krug(8,9,10) ); SlozenLik* sl2 = new SlozenLik(1,1); sl2->Dodaj( new Krug(2,3,4)); sl2->Dodaj( new Kvadrat(2,4,5)); sl.Dodaj(sl2); cout << sl << endl; sl.Pomeri( 15, 26 ); cout << sl << endl; sl.Pomeri( 50, 50 ); sl.Pomeri( 100, 200 ); sl.Pomeri( 150, 250 ); return 0; }

p32.posmatrac.cpp

#define _USE_MATH_DEFINES #include <cmath> #include <iostream> #include <vector> #include <set> #include <string> using namespace std; class Lik; class PosmatracLikova { public: virtual void Azuriraj( Lik&, const char* ) = 0; }; //---------------------------------------------------------------- class Tacka { public: Tacka( double x, double y ) : X_(x), Y_(y) {} private: double X_; double Y_; friend ostream& operator<<( ostream&, const Tacka& ); friend istream& operator>>( istream&, Tacka& ); }; ostream& operator<<( ostream& ostr, const Tacka& t ) { ostr << "(" << t.X_ << "," << t.Y_ << ")"; return ostr; } istream& operator>>( istream& istr, Tacka& a ) { char c1,c2,c3; istr >> c1 >> a.X_ >> c2 >> a.Y_ >> c3; if( c1!='(' || c2!=',' || c3!=')' ) istr.setstate( ios::failbit ); return istr; } //---------------------------------------------------------------- class Lik { public: Lik( double x, double y ) : Polozaj_(x,y) {} virtual ~Lik() {} virtual Lik* Kopija() const = 0; const Tacka& Polozaj() const { return Polozaj_; } Tacka& Polozaj() { return Polozaj_; } // primer promene koja obavestava posmatrace void Pomeri( double nx, double ny ) { Polozaj_ = Tacka( nx, ny ); ObavestiPosmatrace( "pomeren objekat" ); } void DodajPosmatraca( PosmatracLikova* p ) { Posmatraci_.insert(p); } void UkloniPosmatraca( PosmatracLikova* p ) { Posmatraci_.erase(p); } void ObavestiPosmatrace( const char* opis ) { for( auto posmatrac: Posmatraci_ ) posmatrac->Azuriraj( *this, opis ); } virtual double Povrsina() const = 0; private: Tacka Polozaj_; // skup posmatraca set<PosmatracLikova*> Posmatraci_; }; ostream& operator<<( ostream& ostr, const Lik& l ) { ostr << l.Polozaj() << " P=" << l.Povrsina(); return ostr; } //---------------------------------------------------------------- class Pravougaonik : public Lik { public: Pravougaonik( double x, double y, double s, double v ) : Lik(x,y), Sirina_(s), Visina_(v) {} Lik* Kopija() const { return new Pravougaonik(*this); } double Sirina() const { return Sirina_; } double Visina() const { return Visina_; } double Povrsina() const { return Sirina() * Visina(); } private: double Sirina_; double Visina_; }; //---------------------------------------------------------------- class Kvadrat : public Pravougaonik { public: Kvadrat( double x, double y, double a ) : Pravougaonik( x, y, a, a ) {} Lik* Kopija() const { return new Kvadrat(*this); } }; //---------------------------------------------------------------- class Krug : public Lik { public: Krug( double x, double y, double r ) : Lik(x,y), R_(r) {} Lik* Kopija() const { return new Krug(*this); } double R() const { return R_; } double Povrsina() const { return R() * R() * M_PI; } private: double R_; }; //---------------------------------------------------------------- class SlozenLik : public Lik { public: SlozenLik( double x, double y ) : Lik(x,y) {} SlozenLik( const SlozenLik& sl ) : Lik(sl) { init( sl ); } ~SlozenLik() { deinit(); } SlozenLik& operator=( const SlozenLik& sl ) { if( &sl != this ){ deinit(); Polozaj() = sl.Polozaj(); init(sl); } return *this; } Lik* Kopija() const { return new SlozenLik(*this); } void Dodaj( Lik* l ) { Likovi_.push_back(l); } double Povrsina() const { double p = 0; for( auto lik: Likovi_ ) p += lik->Povrsina(); return p; } private: vector<Lik*> Likovi_; void deinit() { for( auto lik: Likovi_ ) delete lik; Likovi_.clear(); } void init( const SlozenLik& sl ) { for( auto lik: sl.Likovi_ ) Dodaj( lik->Kopija() ); } }; //---------------------------------------------------------------- class DnevnikPomeranja : public PosmatracLikova { public: DnevnikPomeranja( const char* ime ) : Ime_(ime) {} void Azuriraj( Lik& lik, const char* opis ) { cout << Ime_ << " : " << opis << " : " << lik << endl; } private: string Ime_; }; //---------------------------------------------------------------- int main() { SlozenLik sl(0,0); sl.Dodaj( new Pravougaonik(1,2,3,4) ); sl.Dodaj( new Kvadrat(5,6,7) ); sl.Dodaj( new Krug(8,9,10) ); SlozenLik* sl2 = new SlozenLik(1,1); sl2->Dodaj( new Krug(2,3,4)); sl2->Dodaj( new Kvadrat(2,4,5)); sl.Dodaj(sl2); cout << sl << endl; sl.Pomeri( 15, 26 ); cout << sl << endl; DnevnikPomeranja d1("D1"); sl.DodajPosmatraca( &d1 ); sl.Pomeri( 50, 50 ); DnevnikPomeranja d2("D2"),d3("D3"); sl.DodajPosmatraca( &d2 ); sl.DodajPosmatraca( &d3 ); sl.Pomeri( 100, 200 ); sl.UkloniPosmatraca( &d2 ); sl.Pomeri( 150, 250 ); return 0; }